#pragma once
#include <vector>
#include <complex>
#include <string>
#include <eigen/Eigen/Dense>
#include <functional>
#include "synth_matlab_bridge.h"
#include "struct_resource.h"
#include "kz_io.h"

// 简单传递函数结构：H(z) = num(z^-1) / den(z^-1)
// struct TF {
//   std::vector<double> num;  // [b0, b1, ..., b_m]
//   std::vector<double> den;  // [1, a1, ..., a_n], 约定 den[0] = 1
// };



// 计算 H(e^{jw})（频响）
std::complex<double> tf_eval(const TF& H, double w);

// 采样法近似 H∞ 范数
double hinf_norm(const StateSpace& G, int worN = 2048, double radius = 1.0 - 1e-9);

// 步骤 1：拉普拉斯 L 的非零特征值（你也可以直接把特征值传进来）
std::vector<double> laplacian_eigs(const std::vector<std::vector<double>>& L);

// 步骤 2：论文参数计算（根据 λ、τ、γ） —— 你把论文里的公式填在 synth.cpp 标记处
struct PaperParams {
  double p1, p1_tilde, p_gamma, p2, p2_tilde, fN, fM,gamma,tau;
};
PaperParams paper_params(double lambda, double tau, double gamma);

// 步骤 2（下半步）：由参数构造各模态的传递函数 \tilde M_i(z)
// 注：这也是论文里给的具体有理式 —— 在 synth.cpp 填上
StateSpace Mi_from_params(const PaperParams& P, double lambda, const TF& ktilde);

// 步骤 3：给定一组 λ≠0，与某个 γ 和 \tilde k(z)，检查 ||\tilde M_i||_∞ < 1 是否全部满足
// bool feasible_gamma(const std::vector<double>& lambdas, double tau,
//                     double gamma, const TF& ktilde, int worN = 4096);

// 新签名：多两个可选输出参数（其中 out_report 你已有时可复用）
bool feasible_gamma(const std::vector<double>& lambdas, double tau,
                    double gamma,
                    TF* out_ktilde,                         // 可为 nullptr
                    tsync::MatlabKtildeReport* out_report); // 可为 nullptr

//步骤 4：对 γ 做二分，返回最小可行 γ
// Find the minimal feasible gamma by bracketing + bisection.
// Returns the (approximate) smallest feasible gamma.
// double search_gamma(const std::vector<double>& lambdas,
//                     double tau,
//                     double g_lo,
//                     double g_hi,
//                     double tol = 1e-2,
//                     int max_iter = 50);
//新签名
double search_gamma(const std::vector<double>& lambdas,
                    double tau,
                    double g_lo,
                    double g_hi,
                    TF& ktilde_best,
                    double tol = 1e-2,
                    int max_iter = 50);
// 步骤 5：根据论文给的 \tilde k(z)=N(z)/D(z) 合成出具体的“统一控制器”
// 最终 k(z) = sqrt(γ*) * \tilde k(z)   （γ* 为上一步二分出来的最小可行值）
struct SynthResult {
  TF ktilde;                 // 归一化控制器
  TF k;                      // 实际控制器（已乘 sqrt(gamma)）
  double gamma_star;         // 最小可行 γ
  // 转换为状态空间（可直接填入你的 Controller 类）—— 可控规范形
  std::vector<double> A, B, C; // A为 n×n 按行存储，B为 n×1，C为 1×n
  double D;
};
SynthResult synth_controller(const std::vector<double>& lambdas,
                             double tau,
                             TF& ktilde_proto,   // 论文给的 N/D 结构（不含 sqrtγ）
                             double g_lo, double g_hi);

// 辅助：从 k(z)=Num/Den 构造可控规范形状态空间（离散）
void tf_to_state_space(const TF& K, std::vector<double>& A,
                       std::vector<double>& B, std::vector<double>& C, double& D);

// 导出系数表到文本
std::string dump_tf(const TF& H);

//新增的类型 别名
using KtildeGen = std::function<TF(double gamma)>;
